package com.zch.rpc.client.client;

import com.zch.rpc.client.common.RpcException;
import com.zch.rpc.client.common.model.RequestModel;
import com.zch.rpc.client.common.model.ResponseModel;
import com.zch.rpc.register.register.ServiceDiscovery;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.UUID;

/**
 * 动态代理的实际处理类，当代理对象每次调用方法的时候都是先执行这里的invoke方法。
 * @param <T>
 */
public class ProxyHandler<T> implements InvocationHandler {
    private ServiceDiscovery serviceDiscovery;
    private Class<T> serviceInterface;//接口的clazz
    private String serviceVerison;



    @Override
    public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {

            // 确定要调用服务的目标主机
            String remoteAddress = serviceDiscovery.discover(serviceInterface.getName(), serviceVerison);

            // 创建 RPC连接
            String[] array = remoteAddress.split(":");
            String host = array[0];
            int port = Integer.parseInt(array[1]);
            //这里依然是socket连接，只不过连接的是服务的提供端了。
            RpcConnector connector = RpcConnector.newInstance(host, port);

            // 初始化 RPC请求对象 设置请求参数
            RequestModel request = new RequestModel();
            //request.setRequestId(UUID.randomUUID().toString());
            request.setServiceVersion(this.serviceVerison);
            request.setInterfaceName(serviceInterface.getName());
            request.setMethodName(method.getName());
            request.setParamTypes(method.getParameterTypes());
            request.setParams(params);

            // 通过里面的socket连接服务端发起请求获取RPC响应对象 基于TCP的短连接,调用后立即释放
            ResponseModel response = connector.remoteInvoke(request);
            if (response.getError() != null) {
                if (response.getError() instanceof RpcException) {
                    throw (RpcException) response.getError();
                } else {
                    throw response.getError();
                }
            }
            return response.getResult();
    }
    public ServiceDiscovery getServiceDiscovery() {
        return serviceDiscovery;
    }

    public void setServiceDiscovery(ServiceDiscovery serviceDiscovery) {
        this.serviceDiscovery = serviceDiscovery;
    }

    public Class<T> getServiceInterface() {
        return serviceInterface;
    }

    public void setServiceInterface(Class<T> serviceInterface) {
        this.serviceInterface = serviceInterface;
    }

    public String getServiceVerison() {
        return serviceVerison;
    }

    public void setServiceVerison(String serviceVerison) {
        this.serviceVerison = serviceVerison;
    }
    public ProxyHandler(ServiceDiscovery serviceDiscovery, Class<T> serviceInterface, String serviceVerison) {
        this.serviceDiscovery = serviceDiscovery;
        this.serviceInterface = serviceInterface;
        this.serviceVerison = serviceVerison;
    }
}
